package com.unswift.window.undo;

import java.util.LinkedList;
import java.util.List;

import javax.swing.text.SimpleAttributeSet;

import com.unswift.utils.ObjectUtils;

public class UndoManager {

	private UndoDocument document;
	private LinkedList<List<UndoAction>> undoList=new LinkedList<List<UndoAction>>();
	private LinkedList<List<UndoAction>> redoList=new LinkedList<List<UndoAction>>();
	
	public UndoManager(UndoDocument document) {
		this.document=document;
		undoList.push(ObjectUtils.asList(new UndoAction(UndoAction.ACTION_FIRST, 0, 0, null)));
	}
	
	public void addEdit(UndoAction undo, boolean newAction){
		if(newAction){
			undoList.push(ObjectUtils.asList(undo));
		}else{
			undoList.peek().add(undo);
		}
		if(undoList.size()>1000){
			undoList.removeLast();
		}
		if(!redoList.isEmpty()){
			redoList=new LinkedList<List<UndoAction>>();
		}
	}
	
	public boolean canUndo(){
		return !undoList.isEmpty();
	}
	
	public void undo(){
		System.out.println("undo");
		try {
			document.setPushUndo(false);
			List<UndoAction> actionList=undoList.poll();
			System.out.println(actionList);
			UndoAction action;
			for (int i = actionList.size()-1; i >=0; i--) {
				action=actionList.get(i);
				if(action.getAction().equals(UndoAction.ACTION_INSERT)){
					document.remove(action.getOffset(), action.getLength());
					action.setAction(UndoAction.ACTION_REMOVE);
				}else if(action.getAction().equals(UndoAction.ACTION_REMOVE)){
					document.insertString(action.getOffset(), action.getText(), new SimpleAttributeSet());
					action.setAction(UndoAction.ACTION_INSERT);
				}else if(action.getAction().equals(UndoAction.ACTION_FIRST)){
					action.setLength(document.getLength());
					action.setText(document.getText());
				}
			}
			redoList.push(actionList);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			document.setPushUndo(true);
		}
	}
	
	public boolean canRedo(){
		return !redoList.isEmpty();
	}
	
	public void redo(){
		System.out.println("undo");
		try {
			document.setPushUndo(false);
			List<UndoAction> actionList=redoList.poll();
			UndoAction action;
			for (int i = 0, length=actionList.size(); i < length; i++) {
				action=actionList.get(i);
				if(action.getAction().equals(UndoAction.ACTION_INSERT)){
					document.remove(action.getOffset(), action.getLength());
					action.setAction(UndoAction.ACTION_REMOVE);
				}else if(action.getAction().equals(UndoAction.ACTION_REMOVE)){
					document.insertString(action.getOffset(), action.getText(), new SimpleAttributeSet());
					action.setAction(UndoAction.ACTION_INSERT);
				}else if(action.getAction().equals(UndoAction.ACTION_FIRST)){
					document.insertString(0, action.getText(), new SimpleAttributeSet());
				}
			}
			undoList.push(actionList);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			document.setPushUndo(true);
		}
	}
}
